home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / x / volume3 / awm2 / part03 < prev    next >
Encoding:
Internet Message Format  |  1989-02-17  |  54.4 KB

  1. Path: uunet!wyse!mikew
  2. From: mikew@wyse.wyse.com (Mike Wexler)
  3. Newsgroups: comp.sources.x
  4. Subject: v03i019:  Ardent Window Manager, Patchlevel 9, Part03/12
  5. Message-ID: <2069@wyse.wyse.com>
  6. Date: 17 Feb 89 19:16:37 GMT
  7. Organization: Wyse Technology, San Jose
  8. Lines: 1987
  9. Approved: mikew@wyse.com
  10.  
  11. Submitted-by: kmw@ardent (Ken Wallich)
  12. Posting-number: Volume 3, Issue 19
  13. Archive-name: awm2/part03
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then unpack
  17. # it by saving it into a file and typing "sh file".  To overwrite existing
  18. # files, type "sh file -c".  You can also feed this as standard input via
  19. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  20. # will see the following message at the end:
  21. #        "End of archive 3 (of 12)."
  22. # Contents:  Resize.c menus/menu.c menus/menu.ext.h
  23. # Wrapped by mikew@wyse on Fri Feb 17 10:50:21 1989
  24. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  25. if test -f 'Resize.c' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'Resize.c'\"
  27. else
  28. echo shar: Extracting \"'Resize.c'\" \(15574 characters\)
  29. sed "s/^X//" >'Resize.c' <<'END_OF_FILE'
  30. X
  31. X
  32. X
  33. X#ifndef lint
  34. Xstatic char *rcsid_Resize_c = "$Header: /usr/graph2/X11.3/contrib/windowmgrs/awm/RCS/Resize.c,v 1.2 89/02/07 21:23:37 jkh Exp $";
  35. X#endif    lint
  36. X
  37. X#include "X11/copyright.h"
  38. X/*
  39. X *
  40. X * Copyright 1987, 1988 by Ardent Computer Corporation, Sunnyvale, Ca.
  41. X *
  42. X * Copyright 1987 by Jordan Hubbard.
  43. X *
  44. X *
  45. X *                         All Rights Reserved
  46. X *
  47. X * Permission to use, copy, modify, and distribute this software and its
  48. X * documentation for any purpose and without fee is hereby granted,
  49. X * provided that the above copyright notice appear in all copies and that
  50. X * both that copyright notice and this permission notice appear in
  51. X * supporting documentation, and that the name of Ardent Computer
  52. X * Corporation or Jordan Hubbard not be used in advertising or publicity
  53. X * pertaining to distribution of the software without specific, written
  54. X * prior permission.
  55. X *
  56. X */
  57. X
  58. X/*
  59. X * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
  60. X *
  61. X *                         All Rights Reserved
  62. X *
  63. X * Permission to use, copy, modify, and distribute this software and its
  64. X * documentation for any purpose and without fee is hereby granted,
  65. X * provided that the above copyright notice appear in all copies and that
  66. X * both that copyright notice and this permission notice appear in
  67. X * supporting documentation, and that the name of Digital Equipment
  68. X * Corporation not be used in advertising or publicity pertaining to
  69. X * distribution of the software without specific, written prior permission.
  70. X *
  71. X *
  72. X * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  73. X * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  74. X * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  75. X * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  76. X * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  77. X * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  78. X * SOFTWARE.
  79. X */
  80. X
  81. X/*
  82. X * MODIFICATION HISTORY
  83. X *
  84. X * 000 -- M. Gancarz, DEC Ultrix Engineering Group
  85. X * 001 -- Loretta Guarino Reid, DEC Ultrix Engineering Group
  86. X *        Convert to X11
  87. X * 002 -- Jordan Hubbard, U.C. berkeley.
  88. X *    Added alternate placement of resize window, code for title bar
  89. X *     support.
  90. X */
  91. X
  92. X#include "awm.h"
  93. X#include "X11/Xutil.h"
  94. X
  95. X#define max(a,b) ( (a) > (b) ? (a) : (b) )
  96. X#define min(a,b) ( (a) > (b) ? (b) : (a) )
  97. X#define makemult(a, b) ((b==1) ? (a) : (((int)((a) / (b))) * (b)) )
  98. X
  99. X/*ARGSUSED*/
  100. XBoolean Resize(window, mask, button, x0, y0)
  101. XWindow window;                          /* Event window. */
  102. Xint mask;                               /* Button/key mask. */
  103. Xint button;                             /* Button event detail. */
  104. Xint x0, y0;                             /* Event mouse position. */
  105. X{
  106. X     XWindowAttributes client_info;    /* client window info. */
  107. X     XWindowAttributes frame_info;    /* frame window info */
  108. X     int x1, y1;                        /* fixed box corner   */
  109. X     int x2, y2;                        /* moving box corner   */
  110. X     int x, y;
  111. X     int xinc, yinc;
  112. X     int minwidth, minheight;
  113. X     int maxwidth, maxheight;
  114. X     int ox, oy;            /* which quadrant of window */
  115. X     int pop_x, pop_y;            /* location of pop window */
  116. X     int hsize, vsize;            /* dynamic size */
  117. X     int delta;    
  118. X     int junk_x, junk_y;
  119. X     unsigned int ptrmask;        /* pointer status word */
  120. X     int num_vectors;            /* Number of vectors to XDraw. */
  121. X     Window sub_win;            /* Mouse query sub window. */
  122. X     Window root;            /* Root query window. */
  123. X     XEvent button_event, *b_ev;    /* Button event packet. */
  124. X     XSegment box[MAX_BOX_VECTORS];    /* Box drawing vertex buffer. */
  125. X     XSegment zap[MAX_ZAP_VECTORS];    /* Zap drawing vertex buffer. */
  126. X     Boolean stop;            /* Should the window stop changing? */
  127. X     XSizeHints sizehints;
  128. X     XWindowChanges values;
  129. X     int width_offset, height_offset;    /* to subtract if resize increments */
  130. X     int x_offset, y_offset;        /* add to pointer to get anchor */
  131. X     AwmInfoPtr awi;
  132. X     int (*storegrid_func)();        /* which StoreGrid routine to use */
  133. X     int (*storebox_func)();        /* which StoreBox routing to use */
  134. X     int buttonConfirmEvent;
  135. X     extern void ungrab_pointer();
  136. X     extern void grab_pointer();
  137. X
  138. X     Entry("Resize")
  139. X
  140. X     /*
  141. X      * Do nothing if the event window is the root window.
  142. X      */
  143. X     if (window == RootWindow(dpy, scr))
  144. X      Leave(FALSE)
  145. X
  146. X     /*
  147. X      * Gather info about the event window.
  148. X      */
  149. X     awi = GetAwmInfo(window);
  150. X     if (!awi)
  151. X      Leave(FALSE)
  152. X     /*
  153. X      * Do not resize an icon window.
  154. X      */
  155. X     if (window == awi->icon)
  156. X      Leave(FALSE)
  157. X
  158. X     window = awi->client;
  159. X     b_ev = &button_event;
  160. X     buttonConfirmEvent = ButtonRelease;
  161. X
  162. X     status = XGetWindowAttributes(dpy, window, &client_info);
  163. X     if (status == FAILURE)
  164. X      Leave(FALSE)
  165. X
  166. X     if (awi->frame) { /* we have to compensate */
  167. X      status = XGetWindowAttributes(dpy, awi->frame, &frame_info);
  168. X      client_info.y = frame_info.y;
  169. X      client_info.x = frame_info.x;
  170. X      if (status == FAILURE)
  171. X           Leave(FALSE)
  172. X          if (DECORATED(awi)) {
  173. X           if (awi->title)
  174. X            client_info.y += titleHeight + 2;
  175. X           if (awi->attrs & AT_BORDER) {
  176. X            client_info.x += BContext + 1;
  177. X            if (!awi->title)
  178. X             client_info.y += BContext + 1;
  179. X           }
  180. X      }
  181. X     }
  182. X
  183. X     /*
  184. X      * Clear The vector buffers.
  185. X      */
  186. X     bzero(box, sizeof(box));
  187. X     if (Zap)
  188. X      bzero(zap, sizeof(zap));
  189. X     storegrid_func = StoreGridBox;
  190. X     storebox_func = StoreBox;
  191. X
  192. X     /*
  193. X      * If we are here then we have a resize operation in progress.
  194. X      */
  195. X     
  196. X     /*
  197. X      * Turn on the resize cursor.
  198. X      */
  199. X     grab_pointer();
  200. X     /*
  201. X      * calculate fixed point (x1, y1) and varying point (x2, y2).
  202. X      */
  203. X     hsize = client_info.width;
  204. X     vsize = client_info.height;
  205. X     x1 = client_info.x;
  206. X     y1 = client_info.y;
  207. X     x2 = x1 + hsize;
  208. X     y2 = y1 + vsize;
  209. X
  210. X     /*
  211. X      * Get the event window resize hint.
  212. X      */
  213. X     sizehints.flags = 0;
  214. X     XGetSizeHints(dpy, window, &sizehints, XA_WM_NORMAL_HINTS); 
  215. X     CheckConsistency(&sizehints);
  216. X
  217. X     /* until there are better WM_HINTS, we'll assume that the client's
  218. X      * minimum width and height are the appropriate offsets to subtract
  219. X      * when resizing with an explicit resize increment.
  220. X      */
  221. X     if ((sizehints.flags & PMinSize) && (sizehints.flags & PResizeInc)) {
  222. X      width_offset = sizehints.min_width;
  223. X      height_offset = sizehints.min_height;
  224. X     } else
  225. X      width_offset = height_offset = 0;
  226. X     /*
  227. X      * decide what resize mode we are in. Always rubberband if window
  228. X      * is too small.
  229. X      */
  230. X     if (client_info.width > 2 && client_info.height > 2) {
  231. X      ox = ((x0 - client_info.x) * 3) / client_info.width;
  232. X      oy = ((y0 - client_info.y) * 3) / client_info.height;
  233. X      if ((ox + oy) & 1) {
  234. X           if (ox & 1) {
  235. X            /* fix up size hints so that we will never change width */
  236. X            sizehints.min_width = sizehints.max_width =
  237. X             client_info.width;
  238. X            if ((sizehints.flags & PMinSize) == 0) {
  239. X             sizehints.min_height = 0;
  240. X             sizehints.flags |= PMinSize;
  241. X            }
  242. X            if ((sizehints.flags & PMaxSize) == 0) {
  243. X             sizehints.max_height = DisplayHeight(dpy, scr);
  244. X             sizehints.flags |= PMaxSize;
  245. X            }
  246. X           }
  247. X           if (oy & 1) {
  248. X            /* fix up size hints so that we will never change height */
  249. X            sizehints.min_height = sizehints.max_height =
  250. X             client_info.height;
  251. X            if ((sizehints.flags & PMinSize)==0) {
  252. X             sizehints.min_width = 0;
  253. X             sizehints.flags |= PMinSize;
  254. X            }
  255. X            if ((sizehints.flags & PMaxSize)==0) {
  256. X             sizehints.max_width = DisplayWidth(dpy, scr);
  257. X             sizehints.flags |= PMaxSize;
  258. X            }
  259. X           }
  260. X      }
  261. X     }
  262. X     else ox = oy = 2;
  263. X     /* change fixed point to one that shouldn't move */
  264. X     if (oy == 0) { 
  265. X      y = y1; y1 = y2; y2 = y;
  266. X     }
  267. X     if (ox == 0) { 
  268. X      x = x1; x1 = x2; x2 = x;
  269. X     }
  270. X     if (sizehints.flags & PMinSize) {
  271. X      minwidth = sizehints.min_width;
  272. X      minheight = sizehints.min_height;
  273. X     } else {
  274. X      minwidth = 0;
  275. X      minheight = 0;
  276. X     }
  277. X     if (sizehints.flags & PMaxSize) {
  278. X      maxwidth = max(sizehints.max_width, minwidth);
  279. X      maxheight = max(sizehints.max_height, minheight);
  280. X     } else {
  281. X      maxwidth = DisplayWidth(dpy, scr);
  282. X      maxheight = DisplayHeight(dpy, scr);
  283. X     }
  284. X     if (sizehints.flags & PResizeInc) {
  285. X      xinc = sizehints.width_inc;
  286. X      yinc = sizehints.height_inc;
  287. X     } else {
  288. X      xinc = 1;
  289. X      yinc = 1;
  290. X     }
  291. X     switch (ox) {
  292. X     case 0:
  293. X      pop_x = x1 - PWidth;
  294. X      break;
  295. X     case 1:
  296. X      pop_x = x1 + (hsize - PWidth) / 2;
  297. X      break;
  298. X     case 2:
  299. X      pop_x = x1;
  300. X      break;
  301. X     }
  302. X     switch (oy) {
  303. X     case 0:
  304. X      pop_y = y1 - PHeight;
  305. X      break;
  306. X     case 1:
  307. X      pop_y = y1 + (vsize - PHeight) / 2;
  308. X      break;
  309. X     case 2:
  310. X      pop_y = y1;
  311. X      break;
  312. X     }
  313. X     /*
  314. X      * Double expose on the target window is too expensive for some reason
  315. X      * or another. Paint the popup window in the upper left hand
  316. X      * corner of the screen if RootResizeBox is FALSE. This is also
  317. X      * more-or-less consistent with the position of the map request popup.
  318. X      */
  319. X     if (RootResizeBox == TRUE)
  320. X      values.x = values.y = 0;
  321. X     else {
  322. X      if (pop_x < 0 || pop_x > (DisplayWidth(dpy, scr) - PWidth))
  323. X           pop_x = 0;
  324. X      if (pop_y < 0 || pop_y > (DisplayHeight(dpy, scr) - PHeight))
  325. X           pop_y = 0;
  326. X      values.x = pop_x;
  327. X      values.y = pop_y;
  328. X     }
  329. X     values.stack_mode = Above;
  330. X     XConfigureWindow(dpy, Pop, (unsigned int) CWX|CWY|CWStackMode, &values);
  331. X     XMapWindow(dpy, Pop);
  332. X     if (Grid) {
  333. X      num_vectors = (*storegrid_func)(box,
  334. X                      MIN(x1, x2), MIN(y1, y2),
  335. X                      MAX(x1, x2), MAX(y1, y2));
  336. X     }
  337. X     else {
  338. X      num_vectors = (*storebox_func)(box,
  339. X                     MIN(x1, x2), MIN(y1, y2),
  340. X                     MAX(x1, x2), MAX(y1, y2));
  341. X     }
  342. X
  343. X     /*
  344. X      * If we freeze the server, then we will draw solid
  345. X      * lines instead of flickering ones during resizing.
  346. X      */
  347. X     if (Freeze)
  348. X      XGrabServer(dpy);
  349. X     /* protect us from ourselves */
  350. X     Snatched = True;
  351. X     /*
  352. X      * Process any pending exposure events before drawing the box.
  353. X      */
  354. X     while (QLength(dpy) > 0) {
  355. X      XPeekEvent(dpy, b_ev);
  356. X      if (b_ev->xany.window == RootWindow(dpy, scr))
  357. X           break;
  358. X      GetButton(b_ev);
  359. X     }
  360. X     if (ResizeRelative) {
  361. X      x_offset = x2 - x0;
  362. X      y_offset = y2 - y0;
  363. X     }
  364. X     else
  365. X      x_offset = y_offset = 0;
  366. X
  367. X     /*
  368. X      * Now draw the box.
  369. X      */
  370. X     DrawBox();
  371. X     Frozen = window;
  372. X     stop = FALSE;
  373. X     x = -1; y = -1;
  374. X     
  375. X     while (!stop) {
  376. X      if (x != x2 || y != y2) {
  377. X           x = x2; y = y2;
  378. X
  379. X           /*
  380. X        * If we've frozen the server, then erase
  381. X        * the old box.
  382. X        */
  383. X           if (Freeze)
  384. X            DrawBox();
  385. X           
  386. X           if (Grid) {
  387. X            num_vectors = (*storegrid_func)(box,
  388. X                            MIN(x1, x), MIN(y1, y),
  389. X                            MAX(x1, x), MAX(y1, y));
  390. X           }
  391. X           else {
  392. X            num_vectors = (*storebox_func)(box,
  393. X                           MIN(x1, x), MIN(y1, y),
  394. X                           MAX(x1, x), MAX(y1, y));
  395. X           }
  396. X           
  397. X           if (Freeze)
  398. X            DrawBox();
  399. X           
  400. X           {
  401. X            int Hsize = (hsize - width_offset) / xinc;
  402. X            int Vsize = (vsize - height_offset) / yinc;
  403. X            int pos = 4;
  404. X            PText[0] = (Hsize>99) ? (Hsize / 100 + '0')      : ' ';
  405. X            PText[1] = (Hsize>9)  ? ((Hsize / 10) % 10 + '0') : ' ';
  406. X            PText[2] = Hsize % 10 + '0';
  407. X            if (Vsize>99) PText[pos++] = Vsize / 100 + '0';
  408. X            if (Vsize>9)  PText[pos++] = (Vsize / 10) % 10 + '0';
  409. X            PText[pos++] = Vsize % 10 + '0';
  410. X            while (pos<7) PText[pos++] = ' ';
  411. X           }
  412. X           /*
  413. X        * If the font is not fixed width we have to
  414. X        * clear the window to guarantee that the characters
  415. X        * that were there before are erased.
  416. X        */
  417. X           if (!(PFontInfo->per_char))
  418. X            XClearWindow(dpy, Pop);
  419. X           XDrawImageString(
  420. X                dpy, Pop, PopGC,
  421. X                PPadding, PPadding+PFontInfo->ascent,
  422. X                PText, PTextSize);
  423. X      }
  424. X      if (!Freeze) {
  425. X           DrawBox();
  426. X           DrawBox();
  427. X      }
  428. X
  429. X      if (XPending(dpy) && !ProcessRequests(box, num_vectors) &&
  430. X          GetButton(b_ev)) {
  431. X           if ((b_ev->xany.type != ButtonPress) && 
  432. X           (b_ev->xany.type != ButtonRelease))
  433. X            continue; /* spurious menu event... */
  434. X
  435. X           if (Freeze) {
  436. X            DrawBox();
  437. X            Frozen = (Window)0;
  438. X            XUngrabServer(dpy);
  439. X           }
  440. X
  441. X           if (b_ev->xany.type == buttonConfirmEvent &&
  442. X           b_ev->xbutton.button == button)
  443. X            stop = TRUE;
  444. X           else {
  445. X            XUnmapWindow(dpy, Pop);
  446. X            ResetCursor(button);
  447. X            Snatched = False;
  448. X            ungrab_pointer();
  449. X            Leave(TRUE)
  450. X           }
  451. X      }
  452. X      else {
  453. X           XQueryPointer(dpy, RootWindow(dpy, scr), &root, 
  454. X                 &sub_win, &x2, &y2, &junk_x, &junk_y, &ptrmask);
  455. X           x2 += x_offset;    /* get to anchor point */
  456. X           y2 += y_offset;
  457. X      }
  458. X      hsize = max(min(abs (x2 - x1), maxwidth), minwidth);
  459. X      hsize = makemult(hsize - minwidth, xinc) + minwidth;
  460. X
  461. X      vsize = max(min(abs(y2 - y1), maxheight), minheight);
  462. X      vsize = makemult(vsize - minheight, yinc) + minheight; 
  463. X      if (sizehints.flags & PAspect) {
  464. X           if ((hsize * sizehints.max_aspect.y > 
  465. X            vsize * sizehints.max_aspect.x)) {
  466. X            delta = makemult((hsize * sizehints.max_aspect.y /
  467. X                      sizehints.max_aspect.x) - vsize, 
  468. X                     yinc);
  469. X            if ((vsize + delta <= maxheight))
  470. X             vsize += delta;
  471. X            else {
  472. X             delta = makemult(hsize - 
  473. X                      (sizehints.max_aspect.x *
  474. X                       vsize/sizehints.max_aspect.y), 
  475. X                      xinc);
  476. X             if (hsize - delta >= minwidth)
  477. X                  hsize -= delta; 
  478. X            }
  479. X           }  
  480. X           if (hsize * sizehints.min_aspect.y < vsize *
  481. X           sizehints.min_aspect.x) {
  482. X            delta = makemult((sizehints.min_aspect.x * 
  483. X                      vsize/sizehints.min_aspect.y) - hsize, 
  484. X                     xinc);
  485. X            if (hsize + delta <= maxwidth)
  486. X             hsize += delta;
  487. X            else {
  488. X             delta = makemult(vsize - 
  489. X                      (hsize*sizehints.min_aspect.y /
  490. X                       sizehints.min_aspect.x), 
  491. X                      yinc); 
  492. X             if (vsize - delta >= minheight)
  493. X                vsize -= delta; 
  494. X            }
  495. X           }
  496. X           
  497. X      }
  498. X      if (ox == 0)
  499. X           x2 = x1 - hsize;
  500. X      else
  501. X           x2 = x1 + hsize;
  502. X      
  503. X      if (oy == 0)
  504. X           y2 = y1 - vsize;
  505. X      else
  506. X           y2 = y1 + vsize;
  507. X      
  508. X     }
  509. X     if (x2 < x1) {
  510. X      x = x1; x1 = x2; x2 = x;
  511. X     }
  512. X     if (y2 < y1) {
  513. X      y = y1; y1 = y2; y2 = y;
  514. X     }
  515. X     XUnmapWindow(dpy, Pop);
  516. X     if ((x1 !=client_info.x) || (y1 != client_info.y) || 
  517. X     (hsize != client_info.width) ||
  518. X     (vsize != client_info.height)) {
  519. X      XWindowChanges xwc;
  520. X           
  521. X      xwc.x = x1;
  522. X      xwc.y = y1;
  523. X      xwc.width = hsize;
  524. X      xwc.height = vsize;
  525. X      ConfigureWindow(window, 
  526. X              (unsigned int) CWX | CWY | CWHeight | CWWidth, &xwc);
  527. X     }
  528. X     Snatched = False;
  529. X     ungrab_pointer();
  530. X     Leave(TRUE)
  531. X}
  532. X
  533. XCheckConsistency(hints)
  534. XXSizeHints *hints;
  535. X{
  536. X     Entry("CheckConsistency")
  537. X
  538. X     if (hints->min_height < 0)
  539. X      hints->min_height = 0;
  540. X     if (hints->min_width < 0)
  541. X      hints->min_width = 0;
  542. X     
  543. X     if (hints->max_height <= 0 || hints->max_width <= 0)
  544. X      hints->flags &= ~PMaxSize;
  545. X     
  546. X     hints->min_height = min(DisplayHeight(dpy, scr), hints->min_height);
  547. X     hints->min_width =  min(DisplayWidth(dpy, scr),  hints->min_width);
  548. X     
  549. X     hints->max_height = min(DisplayHeight(dpy, scr), hints->max_height);
  550. X     hints->max_width =  min(DisplayWidth(dpy, scr),  hints->max_width);
  551. X     
  552. X     if ((hints->flags & PMinSize) && (hints->flags & PMaxSize) && 
  553. X     ((hints->min_height > hints->max_height) ||
  554. X      (hints->min_width > hints->max_width)))
  555. X      hints->flags &= ~(PMinSize|PMaxSize);
  556. X     
  557. X     if ((hints->flags & PAspect) && 
  558. X     (hints->min_aspect.x * hints->max_aspect.y > 
  559. X      hints->max_aspect.x * hints->min_aspect.y))
  560. X      hints->flags &= ~(PAspect);
  561. X     Leave_void
  562. X}
  563. END_OF_FILE
  564. if test 15574 -ne `wc -c <'Resize.c'`; then
  565.     echo shar: \"'Resize.c'\" unpacked with wrong size!
  566. fi
  567. # end of 'Resize.c'
  568. fi
  569. if test -f 'menus/menu.c' -a "${1}" != "-c" ; then 
  570.   echo shar: Will not clobber existing file \"'menus/menu.c'\"
  571. else
  572. echo shar: Extracting \"'menus/menu.c'\" \(33843 characters\)
  573. sed "s/^X//" >'menus/menu.c' <<'END_OF_FILE'
  574. X
  575. X#ifndef lint
  576. X     static char sccs_id[] = "@(#)menu.c    2.1 12/16/87  Siemens Corporate Research and Support, Inc.";
  577. X#endif
  578. X
  579. X
  580. X/*
  581. X  RTL Menu Package Version 1.0
  582. X  by Joe Camaratta and Mike Berman, Siemens RTL, Princeton NJ, 1987
  583. X  
  584. X  menu.c: menu utility and support functions.
  585. X  
  586. X  Originally hacked by Adam J. Richter, based on the menu package for xterm.
  587. X  ( misc.c  X10/6.6 )
  588. X
  589. X  */
  590. X
  591. X/*
  592. X *
  593. X * Changed in various and subtle ways by Jordan Hubbard, Ardent Computer.
  594. X * February 1st, 1988: Removed dependence on oldX by nuking AssocTable
  595. X * stuff in favor of contexts. Added "label" panes, useful for titling
  596. X * purposes. Variable height items, variable fonts, pictoral panes
  597. X * (pixmaps) for cute graphic menus.
  598. X */
  599. X
  600. X/*
  601. X *
  602. X * Copyright 1987, 1988 by Ardent Computer Corporation, Sunnyvale, Ca.
  603. X *
  604. X * Copyright 1987 by Jordan Hubbard.
  605. X *
  606. X *
  607. X *                         All Rights Reserved
  608. X *
  609. X * Permission to use, copy, modify, and distribute this software and its
  610. X * documentation for any purpose and without fee is hereby granted,
  611. X * provided that the above copyright notice appear in all copies and that
  612. X * both that copyright notice and this permission notice appear in
  613. X * supporting documentation, and that the name of Ardent Computer
  614. X * Corporation or Jordan Hubbard not be used in advertising or publicity
  615. X * pertaining to distribution of the software without specific, written
  616. X * prior permission.
  617. X *
  618. X */
  619. X
  620. X
  621. X/*
  622. X  
  623. X  Copyright 1987 by
  624. X  Siemens Corporate Research and Support, Inc., Princeton, New Jersey
  625. X  
  626. X  Permission to use, copy, modify, and distribute this software
  627. X  and its documentation for any purpose and without fee is
  628. X  hereby granted, provided that the above copyright notice
  629. X  appear in all copies and that both that copyright notice and
  630. X  this permission notice appear in supporting documentation, and
  631. X  that the name of Siemens not be used in advertising or
  632. X  publicity pertaining to distribution of the software without
  633. X  specific, written prior permission.  Siemens makes no
  634. X  representations about the suitability of this software for any
  635. X  purpose.  It is provided "as is" without express or implied
  636. X  warranty.
  637. X  
  638. X  */
  639. X
  640. X/*
  641. X  
  642. X  Copyright 1985, 1986, 1987 by the Massachusetts Institute of Technology
  643. X  
  644. X  Permission to use, copy, modify, and distribute this
  645. X  software and its documentation for any purpose and without
  646. X  fee is hereby granted, provided that the above copyright
  647. X  notice appear in all copies and that both that copyright
  648. X  notice and this permission notice appear in supporting
  649. X  documentation, and that the name of M.I.T. not be used in
  650. X  advertising or publicity pertaining to distribution of the
  651. X  software without specific, written prior permission.
  652. X  M.I.T. makes no representations about the suitability of
  653. X  this software for any purpose.  It is provided "as is"
  654. X  without express or implied warranty.
  655. X  
  656. X  */
  657. X
  658. X/*
  659. X * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
  660. X *
  661. X *               All Rights Reserved
  662. X *
  663. X * Permission to use, copy, modify, and distribute this software and its
  664. X * documentation for any purpose and without fee is hereby granted,
  665. X * provided that the above copyright notice appear in all copies and that
  666. X * both that copyright notice and this permission notice appear in
  667. X * supporting documentation, and that the name of Digital Equipment
  668. X * Corporation not be used in advertising or publicity pertaining to
  669. X * distribution of the software without specific, written prior permission.
  670. X *
  671. X *
  672. X * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  673. X * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  674. X * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  675. X * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  676. X * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  677. X * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  678. X * SOFTWARE.
  679. X */
  680. X
  681. X/* Got that?  Good! Now, there is actually some code in here.. */
  682. X
  683. X
  684. X#include <stdio.h>
  685. X#include "X11/Xlib.h"
  686. X#include "X11/cursorfont.h"
  687. X#include "X11/Xutil.h"
  688. X#include "X11/Intrinsic.h"
  689. X
  690. X#include "menu.h"
  691. X#include "menu.def.h"
  692. X#include "gray1.h"
  693. X#include "arrow_icon.h"
  694. X#include "dbug.h"
  695. X
  696. X#define MakeEven(x) ((x%2 == 0)? x : x-1)
  697. X
  698. X
  699. X#define InvertPlane        1
  700. X
  701. Xstatic char Check_MarkBits[] = {
  702. X     0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00,
  703. X     0x31, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0x04, 0x00
  704. X     };
  705. X
  706. XMenu MenuDefault;
  707. X
  708. X/*
  709. X * the following have already been set my GetDefaults()
  710. X * by the time we get here.
  711. X */
  712. XXFontStruct *MFontInfo;
  713. XXFontStruct *MBoldFontInfo;
  714. Xint MBorderWidth, MPad, MDelta, MItemBorder;
  715. XPixel MForeground, MBackground, MBorder;
  716. X
  717. Xextern Boolean SaveUnder;
  718. Xextern int Reverse;
  719. Xextern Display *dpy;
  720. Xextern int scr;
  721. X
  722. Xstatic XContext Menu_context;
  723. Xstatic XContext Item_context;
  724. Xstatic contexts_created = FALSE;
  725. X
  726. XMenuItem *AddMenuItem(), *Display_Menu(), *MenuGetItem(),
  727. X     *MenuItemByName(), *MenuItemByData(), *GetInitialItem(), *MoveMenu();
  728. XBoolean     DisposeItem(), SetItemCheck(), SetItemDisable(), Recalc_Menu(),
  729. X     SetupItems(), MapMenu(), SetItemText(), SetupMenuWindow();
  730. Xvoid     DisposeMenu(), InitMenu(), Undisplay_Menu(), MenuInvert(),
  731. X     PlacePointer(), Draw_Menu(), Draw_Item(),    SetInitialItem(),
  732. X     ClearInitialItem(), Generate_Menu_Entries(), UnmapMenu(),
  733. X     SetInputMask();
  734. XMenu     *NewMenu(), *MenuGetMenu();
  735. Xint     ItemGetMiddleY();
  736. X
  737. X/*
  738. X * AddMenuItem() adds a menu item to an existing menu, at the end of the
  739. X * list, which are number sequentially from zero.  The menuitem index is
  740. X * return, or -1 if failed.
  741. X */
  742. X
  743. XMenuItem *AddMenuItem(menu, text, bitmap_file)
  744. XMenu *menu;
  745. Xchar *text;
  746. Xchar *bitmap_file;
  747. X{
  748. X     MenuItem *menuitem, **next;
  749. X     int junk;
  750. X     char *data;
  751. X
  752. X     Entry("AddMenuItem")
  753. X
  754. X     if (!menu || (!text && !bitmap_file) || (menuitem = allocate(MenuItem, 1))
  755. X    == (MenuItem *)0)
  756. X      Leave(NULLITEM)
  757. X     bzero((char *)menuitem, sizeof(MenuItem));
  758. X     ItemText(menuitem) = allocate(char, (strlen(text) + 1));
  759. X     strcpy(ItemText(menuitem), text);
  760. X     ItemTextLength(menuitem) = strlen(text);
  761. X     if (bitmap_file) {
  762. X      bitmap_file = (char *)expand_from_path(bitmap_file);
  763. X      if (XmuReadBitmapDataFromFile(bitmap_file,
  764. X                  &(menuitem->itemTextWidth),
  765. X                  &(menuitem->itemHeight),
  766. X                  &data,
  767. X                  &junk, &junk) != BitmapSuccess) {
  768. X           fprintf(stderr, "awm: Can't read bitmap file '%s'\n",
  769. X               bitmap_file);
  770. X           exit(1);
  771. X      }
  772. X      menuitem->itemBackground =
  773. X           XCreatePixmapFromBitmapData(dpy, RootWindow(dpy, scr),
  774. X                       data,
  775. X                       menuitem->itemTextWidth,
  776. X                       menuitem->itemHeight,
  777. X                       MForeground,
  778. X                       MBackground,
  779. X                       DefaultDepth(dpy, scr));
  780. X      if (!menuitem->itemBackground) {
  781. X           fprintf(stderr, "awm: Can't create pixmap for file '%s'\n",
  782. X               bitmap_file);
  783. X           exit(1);
  784. X      }
  785. X      free(data);
  786. X      free(bitmap_file);
  787. X     }
  788. X     for(next = &menu->menuItems; *next; next = &(*next)->nextItem);
  789. X
  790. X     *next = menuitem;
  791. X
  792. X     SetMenuFlag(menu, menuChanged);
  793. X     Leave(menuitem)
  794. X}
  795. X
  796. X/*
  797. X * DisposeItem() releases the memory allocated for the given indexed
  798. X * menuitem.  Nonzero is returned if an item was actual disposed of.
  799. X * It also checks to see whether the item we're disposing is the
  800. X * initial item for the menu -- if so, null out the initial item.
  801. X */
  802. XBoolean DisposeItem(menu, item)
  803. XMenu *menu;
  804. XMenuItem *item;
  805. X{
  806. X     MenuItem **next, **last, *menuitem;
  807. X     Entry("DisposeItem")
  808. X
  809. X     if (MenuIsNull(menu) || ItemIsNull(item))
  810. X      Leave(FALSE)
  811. X     next = &MenuItems(menu);
  812. X     do {
  813. X      if(!*next)
  814. X           Leave(FALSE)
  815. X      last = next;
  816. X      next = &(*next)->nextItem;
  817. X     } while((*last != item) && !ItemIsNull(*next));
  818. X     menuitem = *last;
  819. X     *last = *next;
  820. X     if (ItemWindow(menuitem)) {
  821. X      XDeleteContext(dpy, ItemWindow(menuitem), Item_context);
  822. X      XDestroyWindow(dpy, ItemWindow(menuitem));
  823. X     }
  824. X     if (ItemIsInitialItem(menu, menuitem))
  825. X      ClearInitialItem(menu);
  826. X
  827. X     if (ItemText(menuitem))
  828. X      free((char*)ItemText(menuitem));
  829. X     free((char*)menuitem);
  830. X
  831. X     SetMenuFlag(menu, menuChanged);
  832. X     Leave(TRUE)
  833. X}
  834. X
  835. X/*
  836. X * DisposeMenu() releases the memory allocated for the given menu.
  837. X */
  838. Xvoid DisposeMenu(menu)
  839. XMenu *menu;
  840. X{
  841. X     Entry("DisposeMenu")
  842. X
  843. X     if(!menu)
  844. X      Leave_void
  845. X     if (TestMenuFlag(menu, menuMapped))
  846. X      UnmapMenu(menu);
  847. X     while(DisposeItem(menu, MenuItems(menu)));
  848. X     if(MenuWindow(menu)) {
  849. X      XDeleteContext(dpy, MenuWindow(menu), Menu_context);
  850. X      XDestroyWindow(dpy, MenuWindow(menu));
  851. X     }
  852. X     XFreePixmap (dpy, MenuGreyPixmap(menu));
  853. X     XFreePixmap (dpy, MenuArrowPixmap(menu));
  854. X     XFreePixmap (dpy, MenuCheckmarkPixmap(menu));
  855. X     XFreeGC (dpy, MenuNormalGC(menu));
  856. X     XFreeGC (dpy, MenuInvertGC(menu));
  857. X     XFreeGC (dpy, menu->boldGC);
  858. X     
  859. X     if (MenuHasInitialItem(menu))
  860. X      ClearInitialItem(menu);
  861. X     free((char*) menu);
  862. X     Leave_void
  863. X}
  864. X
  865. Xstatic char *Name;
  866. X
  867. Xvoid InitMenu(name, options)
  868. Xchar *name;
  869. Xunsigned int options;
  870. X{
  871. X     char *cp;
  872. X     
  873. X     Entry("InitMenu")
  874. X
  875. X     Name = name;
  876. X     MenuDefault.menuFlags = menuChanged;
  877. X     
  878. X     MenuDefault.menuInitialItemText = (char *) NULL;
  879. X     MenuDefault.display = dpy;
  880. X     MenuDefault.screen = scr;
  881. X     MenuDefault.menuOptions = options;
  882. X     Leave_void
  883. X}
  884. X
  885. X/*
  886. X * ItemText changes the text of item of the menu.
  887. X */
  888. XBoolean SetItemText(menu, item, text)
  889. XMenu *menu;
  890. XMenuItem *item;
  891. Xchar *text;
  892. X{
  893. X     Entry("SetItemText")
  894. X
  895. X     if (strcmp (ItemText(item), text) == 0)
  896. X      Leave (True)
  897. X     
  898. X     if(ItemText(item))
  899. X      free((char *) ItemText(item));
  900. X     
  901. X     ItemText(item) = allocate(char, (strlen(text) + 1));
  902. X     strcpy(ItemText(item), text);
  903. X     
  904. X     ItemTextLength(item) = strlen (text);
  905. X     SetMenuFlag(menu, menuChanged);
  906. X     
  907. X     (void) Recalc_Menu (menu);
  908. X     Leave(TRUE)
  909. X}
  910. X
  911. X/*
  912. X * NewMenu() returns a pointer to an initialized new Menu structure, or NULL
  913. X * if failed.
  914. X *
  915. X * The Menu structure _menuDefault contains the default menu settings.
  916. X */
  917. XMenu *NewMenu()
  918. X{
  919. X     extern Pixmap MakeGreyStipple ();
  920. X     Menu *menu = 0;
  921. X     
  922. X     XGCValues gcValues;
  923. X     
  924. X     static unsigned long gcMask =
  925. X      (GCFunction | GCForeground | GCBackground | GCFont | GCStipple |
  926. X       GCSubwindowMode | GCGraphicsExposures);
  927. X     
  928. X     char *cp;
  929. X
  930. X     Entry("NewMenu")
  931. X
  932. X     /*
  933. X      * Allocate the memory for the menu structure.
  934. X      */
  935. X     if(MenuIsNull((menu = allocate(Menu, 1))))
  936. X      Leave(NULLMENU)
  937. X     
  938. X     /*
  939. X      * Initialize to default values.
  940. X      */
  941. X     *menu = MenuDefault;
  942. X     gcValues.font = MFontInfo->fid;
  943. X     
  944. X     /*
  945. X      * If the menu cursor hasn't been given, make a default one.
  946. X      */
  947. X
  948. X     MenuCursor(menu) = XCreateFontCursor (dpy, XC_right_ptr);
  949. X     MenuArrowPixmap(menu) = XCreatePixmapFromBitmapData(dpy,
  950. X                             RootWindow(dpy, scr),
  951. X                             arrow_bits,
  952. X                             arrow_width,
  953. X                             arrow_height,
  954. X                             MForeground,
  955. X                             MBackground,
  956. X                             DefaultDepth(dpy, scr));
  957. X
  958. X     MenuGreyPixmap(menu) = XCreateBitmapFromData(dpy,
  959. X                          RootWindow(dpy, scr),
  960. X                          gray1_bits,
  961. X                          gray1_width, gray1_height);
  962. X     
  963. X     MenuCheckmarkPixmap(menu) = XCreatePixmapFromBitmapData(dpy,
  964. X                                 RootWindow(dpy, scr),
  965. X                                 Check_MarkBits,
  966. X                                 checkMarkWidth,
  967. X                                 checkMarkHeight,
  968. X                                 MForeground,
  969. X                                 MBackground,
  970. X                                 DefaultDepth(dpy, scr));
  971. X
  972. X     gcValues.foreground = MForeground;
  973. X     gcValues.background = MBackground;
  974. X
  975. X     gcValues.stipple = MenuGreyPixmap(menu);
  976. X     gcValues.function = GXcopy;
  977. X     gcValues.subwindow_mode = IncludeInferiors;
  978. X     gcValues.graphics_exposures = False;
  979. X     MenuNormalGC(menu) =
  980. X      XCreateGC (dpy, RootWindow(dpy, scr),
  981. X             gcMask,
  982. X             &gcValues);
  983. X     /* reverse */
  984. X     gcValues.foreground = MBackground;
  985. X     gcValues.background = MForeground;
  986. X
  987. X     MenuInvertGC(menu) = XCreateGC(dpy, RootWindow (dpy, scr),
  988. X                    gcMask,
  989. X                    &gcValues);
  990. X     gcValues.foreground = MForeground;
  991. X     gcValues.background = MBackground;
  992. X     gcValues.font = MBoldFontInfo->fid;
  993. X     menu->boldGC = XCreateGC(dpy, RootWindow(dpy, scr),
  994. X                  gcMask,
  995. X                  &gcValues);
  996. X     Leave(menu)
  997. X}
  998. X
  999. X
  1000. X/*
  1001. X * SetItemCheck sets the check state of item of the menu to "state".
  1002. X */
  1003. XBoolean SetItemCheck(menu, item, state)
  1004. XMenu *menu;
  1005. XMenuItem *item;
  1006. Xint state;
  1007. X{
  1008. X     Entry("SetItemCheck")
  1009. X
  1010. X     if (TestItemFlag(item,itemChecked) == state) /* Exit if unchanged */
  1011. X      Leave (True)
  1012. X     
  1013. X     if (state)
  1014. X      SetItemFlag(item, itemChecked);
  1015. X     else
  1016. X      ResetItemFlag(item, itemChecked);
  1017. X     
  1018. X     SetItemFlag(item, itemChanged);
  1019. X     SetMenuFlag(menu, menuItemChanged);
  1020. X     
  1021. X     Leave(TRUE)
  1022. X}
  1023. X/*
  1024. X * SetItemDeaf sets the "deaf" state of item of the menu to "state".
  1025. X * "deaf" means that the item is display only and not sensitive to input.
  1026. X */
  1027. XBoolean SetItemDeaf(menu, item, state)
  1028. XMenu *menu;
  1029. XMenuItem *item;
  1030. Xint state;
  1031. X{
  1032. X     Entry("SetItemDeaf")
  1033. X
  1034. X     if (TestItemFlag(item,itemDeaf) == state) /* Exit if unchanged */
  1035. X      Leave (True)
  1036. X     
  1037. X     if (state)
  1038. X      SetItemFlag(item, itemDeaf);
  1039. X     else
  1040. X      ResetItemFlag(item, itemDeaf);
  1041. X     
  1042. X     SetItemFlag(item, itemChanged);
  1043. X     SetMenuFlag(menu, menuItemChanged);
  1044. X     if (ItemIsInitialItem(menu, item))
  1045. X      ClearInitialItem(menu);
  1046. X     Leave(TRUE)
  1047. X}
  1048. X
  1049. X/*
  1050. X * SetItemDisable sets the disable state of item "n" of the menu to "state".
  1051. X */
  1052. XBoolean SetItemDisable(menu, item, state)
  1053. XMenu *menu;
  1054. XMenuItem *item;
  1055. Xint state;
  1056. X{
  1057. X     Entry("SetItemDisable")
  1058. X
  1059. X     if (TestItemFlag(item,itemDisabled) == state) /* Exit if unchanged */
  1060. X      Leave (True)
  1061. X     
  1062. X     if(state)
  1063. X     {
  1064. X      SetItemFlag(item, itemDisabled);
  1065. X      /* if disabled item is currently initial item, null initial item */
  1066. X      if (ItemIsInitialItem(menu, item))
  1067. X           ClearInitialItem(menu);
  1068. X     }
  1069. X     else
  1070. X      ResetItemFlag(item, itemDisabled);
  1071. X     
  1072. X     SetItemFlag(item, itemChanged);
  1073. X     SetMenuFlag(menu, menuItemChanged);
  1074. X     
  1075. X     Leave(TRUE)
  1076. X}
  1077. X
  1078. XMenuItem *Display_Menu(menu, parent, x, y)
  1079. XMenu *menu;
  1080. XMenu *parent;
  1081. Xint x;
  1082. Xint y;
  1083. X{
  1084. X     MenuItem *item;
  1085. X     
  1086. X     Entry("Display_Menu")
  1087. X
  1088. X     if (MenuIsNull(menu))
  1089. X      Leave(FALSE)
  1090. X     
  1091. X     MenuParent(menu) = parent;
  1092. X     
  1093. X     if (MenuIsNull(parent))
  1094. X      MenuNested(menu) = 0;
  1095. X     else
  1096. X      MenuNested(menu) = MenuNested(parent) + 1;
  1097. X     if (!MenuWindow(menu) || TestMenuFlag(menu,
  1098. X        (menuChanged | menuItemChanged))) {
  1099. X      if (!SetupMenuWindow(menu))
  1100. X           Leave(NULL)
  1101. X      Generate_Menu_Entries(menu);
  1102. X     }
  1103. X     if (TestOptionFlag(menu,savebits) &&
  1104. X     (MenuSavedPixmap(menu) != (Pixmap) 0))
  1105. X      SetInputMask(menu, MenuIgnoreMask);
  1106. X     else
  1107. X      SetInputMask(menu, ExposureMask);
  1108. X     if (!(item = MoveMenu(menu, x, y)) || !MapMenu(menu))
  1109. X      Leave(FALSE)
  1110. X     Draw_Menu(menu);
  1111. X     
  1112. X     Leave(item)
  1113. X}
  1114. X
  1115. Xvoid Undisplay_Menu(menu)
  1116. XMenu *menu;
  1117. X{
  1118. X     Entry("Undisplay_Menu")
  1119. X
  1120. X     if (MenuIsNull(menu))
  1121. X      Leave_void
  1122. X     
  1123. X     MenuParent(menu) = NULLMENU;
  1124. X     MenuNested(menu) = 0;
  1125. X     
  1126. X     UnmapMenu(menu);
  1127. X     Leave_void
  1128. X}
  1129. X
  1130. Xvoid MenuInvert(menu, item)
  1131. XMenu *menu;
  1132. XMenuItem *item;
  1133. X{
  1134. X     Entry("MenuInvert")
  1135. X
  1136. X     XFillRectangle(dpy,
  1137. X            ItemWindow(item),
  1138. X            MenuInvertGC(menu),
  1139. X            0, 0, 
  1140. X            MenuWidth(menu),
  1141. X            item->itemHeight);
  1142. X     Leave_void
  1143. X}
  1144. X
  1145. X/*
  1146. X * Recalculate all of the various menu and item variables.
  1147. X */
  1148. XBoolean Recalc_Menu(menu)
  1149. XMenu *menu;
  1150. X{
  1151. X     MenuItem *item;
  1152. X     int max, height, fontheight, boldfontheight, nitems;
  1153. X     /* Gets set to false first time we see an item with text */
  1154. X     unsigned int menuIsPictures = TRUE;
  1155. X     
  1156. X     Entry("Recalc_Menu")
  1157. X
  1158. X     /*
  1159. X      * We must have already gotten the menu font.
  1160. X      */
  1161. X     if(!MFontInfo)
  1162. X      Leave(FALSE)
  1163. X     /*
  1164. X      * Initialize the various max width variables.
  1165. X      */
  1166. X     fontheight = MFontInfo->ascent + MFontInfo->descent + 2;
  1167. X     boldfontheight = MBoldFontInfo->ascent + MBoldFontInfo->descent + 2;
  1168. X     height = nitems = 0;
  1169. X     MenuMaxTextWidth(menu) = 0;
  1170. X     /*
  1171. X      * The item height is the maximum of the font height and the
  1172. X      * checkbox height, unless we find out that it's a pixmap (in which
  1173. X      * case, most of these values are overridden).
  1174. X      */
  1175. X     max = fontheight;
  1176. X     if(checkMarkHeight > max)
  1177. X      max = checkMarkHeight;
  1178. X     
  1179. X     max += 2*MItemBorder;
  1180. X     max = MakeEven(max);
  1181. X             
  1182. X     /*
  1183. X      * Go through the menu item list.
  1184. X      */
  1185. X     for(item = MenuItems(menu) ; item ; item = ItemNext(item)) {
  1186. X      if (item->itemBackground)    /* pixmap is static size */
  1187. X           max = item->itemHeight;
  1188. X      else {
  1189. X           if (ItemIsDeaf(item))    /* It's a label, use bold info */
  1190. X            max = boldfontheight;
  1191. X           else
  1192. X            max = fontheight;
  1193. X      }
  1194. X      if (checkMarkHeight > max)
  1195. X           max = checkMarkHeight;
  1196. X      if (!item->itemBackground) {
  1197. X           max += 2 * MItemBorder;
  1198. X           max = MakeEven(max);
  1199. X           item->itemHeight = max;
  1200. X      }
  1201. X      height += max;
  1202. X      nitems++;
  1203. X      /*
  1204. X       * Check the text width with the max value stored in
  1205. X       * menu.
  1206. X       */
  1207. X      if (!item->itemBackground) {
  1208. X           if ((ItemTextWidth(item) = XTextWidth(ItemIsDeaf(item) ?
  1209. X                             MBoldFontInfo
  1210. X                             : MFontInfo,
  1211. X                             ItemText(item),
  1212. X                             strlen (ItemText(item))))
  1213. X                  > MenuMaxTextWidth(menu))
  1214. X                    MenuMaxTextWidth(menu) = ItemTextWidth(item);
  1215. X           menuIsPictures = FALSE;
  1216. X          }
  1217. X          /* ItemTextWidth is really pixmap size. Yick. */
  1218. X      else {
  1219. X               if (ItemTextWidth(item) > MenuMaxTextWidth(menu))
  1220. X                    MenuMaxTextWidth(menu) = ItemTextWidth(item);
  1221. X          }
  1222. X
  1223. X     }
  1224. X     /*
  1225. X      * Set the menu height and then set the menu width.
  1226. X      */
  1227. X     MenuHeight(menu) = height;
  1228. X     menu->avgHeight = height / nitems;
  1229. X
  1230. X     if (menuIsPictures == TRUE)
  1231. X      MenuWidth(menu) = MenuMaxTextWidth(menu) + (2 * MItemBorder);
  1232. X     else {
  1233. X      MenuWidth(menu) = 4 * MenuItemPad(menu) + MenuMaxTextWidth(menu) +
  1234. X           checkMarkWidth + arrow_width + (2 * MItemBorder);
  1235. X     }
  1236. X     MenuItemWidth(menu) = MenuWidth(menu) - (2 * MItemBorder);
  1237. X     Leave(TRUE)
  1238. X}
  1239. X
  1240. X/*
  1241. X * Figure out where to popup the menu, relative to the where the button was
  1242. X * pressed.
  1243. X * Returns pointer to initial item to warp to.
  1244. X */
  1245. Xstatic MenuItem *MoveMenu(menu, ev_x, ev_y)
  1246. XMenu *menu;
  1247. Xint ev_x, ev_y;
  1248. X{
  1249. X     int x, y;
  1250. X     int total_width, total_height;
  1251. X     int offset;
  1252. X     MenuItem *item;
  1253. X     Window junk;
  1254. X     int r_x, foo, state;
  1255. X     
  1256. X     Entry("MoveMenu")
  1257. X
  1258. X     /*
  1259. X      * Get the coordinates of the mouse when the button was pressed.
  1260. X      */
  1261. X     
  1262. X     total_width = MenuWidth(menu) + 2 * MenuBorderWidth(menu);
  1263. X     total_height = MenuHeight(menu) + 2 * MenuBorderWidth(menu);
  1264. X
  1265. X     XQueryPointer(dpy, RootWindow(dpy, scr), &junk, &junk, &r_x, &y,
  1266. X           &foo, &foo, &state); 
  1267. X     x = ev_x - MenuItemPad(menu);
  1268. X     if (x < 0)
  1269. X      x = 0;
  1270. X     else if (TestOptionFlag(menu, rightoffset) &&
  1271. X          !MenuIsNull(MenuParent(menu)))
  1272. X     {
  1273. X      /* check whether parent is close to right edge... */
  1274. X      /* "too close" means that child would leave < delta of its parent */
  1275. X      /* visible to its left.                                           */
  1276. X      if (TestOptionFlag(menu, bigoffset))
  1277. X      {
  1278. X           if (MenuX(MenuParent(menu)) + MenuWidth(MenuParent(menu)) > 
  1279. X           DisplayWidth(dpy, scr) - total_width)
  1280. X            x = MenuX(MenuParent(menu))
  1281. X             - total_width + 2*MenuBorderWidth(menu);
  1282. X      }
  1283. X      else
  1284. X      {
  1285. X           if (MenuX(MenuParent(menu)) + MenuDelta(MenuParent(menu)) > 
  1286. X           DisplayWidth(dpy, scr) - total_width)
  1287. X           {
  1288. X            x = (MenuX(MenuParent(menu)) + MenuWidth(MenuParent(menu)) +
  1289. X             2 * MenuBorderWidth(MenuParent(menu))
  1290. X             - total_width - MenuDelta(menu));
  1291. X           }
  1292. X      }
  1293. X     }
  1294. X     if (x + total_width >
  1295. X     DisplayWidth(dpy, scr))
  1296. X      x = DisplayWidth(dpy, scr)
  1297. X           - total_width;
  1298. X     
  1299. X     /*
  1300. X      * If we have an initial item, try to popup the menu centered
  1301. X      * vertically within this item.
  1302. X      */
  1303. X     if(MenuHasInitialItem(menu)) {
  1304. X      int tmp_y;
  1305. X
  1306. X      /*
  1307. X       * Look through the item list. "y" is the vertical position
  1308. X       * of the top of the current item and "n" is the item number.
  1309. X       */
  1310. X      offset = MenuBorderWidth(menu);
  1311. X      for(item = MenuItems(menu) ; ;) {
  1312. X           /*
  1313. X        * On finding the initial item, center within this item.
  1314. X        */
  1315. X           if (ItemIsInitialItem(menu, item)) {
  1316. X            y -= offset;
  1317. X            break;
  1318. X           }
  1319. X           else
  1320. X            offset += item->itemHeight;
  1321. X           /*
  1322. X        * If we run out of items, turn off the initial item
  1323. X        * and treat this as if no initial item.
  1324. X        */
  1325. X           if(!(item = ItemNext(item))) {
  1326. X            ClearInitialItem(menu);
  1327. X            break;
  1328. X           }
  1329. X      }
  1330. X     }
  1331. X     
  1332. X     if (y < 0)
  1333. X      y = 0;
  1334. X     else if (y + total_height >
  1335. X          DisplayHeight(dpy, scr))
  1336. X     {
  1337. X      y = DisplayHeight(dpy, scr)
  1338. X           - (total_height + 1);
  1339. X     }
  1340. X     y = MakeEven(y) + 1;
  1341. X     XMoveWindow(dpy, MenuWindow(menu), x, y);
  1342. X     MenuX(menu) = x;
  1343. X     MenuY(menu) = y;
  1344. X     
  1345. X     if (!ItemIsInitialItem(menu, item))
  1346. X      item = MenuItems(menu);
  1347. X     Leave(item)
  1348. X}
  1349. X
  1350. X
  1351. Xvoid PlacePointer(menu, item)
  1352. XMenu *menu;
  1353. XMenuItem *item;
  1354. X{
  1355. X     int y;
  1356. X     
  1357. X     Entry("PlacePointer")
  1358. X
  1359. X     y = ItemGetMiddleY(item);
  1360. X     
  1361. X     XWarpPointer(dpy, None,
  1362. X          RootWindow(dpy, scr), 
  1363. X          0, 0, 0, 0, 
  1364. X          MenuX(menu) + MPad + (MenuWidth(menu) / 2), y);
  1365. X     Leave_void
  1366. X}
  1367. X
  1368. X/*
  1369. X * Map the menu window.
  1370. X */
  1371. Xstatic Boolean MapMenu(menu)
  1372. XMenu *menu;
  1373. X{
  1374. X     Entry("MapMenu")
  1375. X
  1376. X     if (!TestMenuFlag(menu, menuMapped))
  1377. X      MenuItemHighlighted(menu) = NULLITEM;
  1378. X     
  1379. X     /*
  1380. X      * Actually map the window.
  1381. X      */
  1382. X     
  1383. X     if (TestOptionFlag(menu,savebits))
  1384. X     {
  1385. X      if ((MenuSavedPixmap(menu) == (Pixmap) 0) ||
  1386. X          (MenuOldWidth(menu) != MenuWidth(menu)) ||
  1387. X          (MenuOldHeight(menu) != MenuHeight(menu)) ||
  1388. X          (MenuOldBorderWidth(menu) != MenuBorderWidth(menu)))
  1389. X      {
  1390. X           if (MenuSavedPixmap(menu) != (Pixmap) 0)
  1391. X            XFreePixmap(dpy, MenuSavedPixmap(menu));
  1392. X           
  1393. X           MenuSavedPixmap(menu) =
  1394. X            XCreatePixmap(dpy, 
  1395. X                  RootWindow(dpy, scr), 
  1396. X                  MenuWidth(menu) + 2*MenuBorderWidth(menu),
  1397. X                  MenuHeight(menu) + 2*MenuBorderWidth(menu),
  1398. X                  DefaultDepth(dpy, scr));
  1399. X           DBUG_5("Pixmaps","Created pixmap: width %d, height %d, depth %d\n",
  1400. X              MenuWidth(menu) + 2*MenuBorderWidth(menu),
  1401. X              MenuHeight(menu) + 2*MenuBorderWidth(menu),
  1402. X              DefaultDepth(dpy, scr)); 
  1403. X           MenuOldWidth(menu) = MenuWidth(menu);
  1404. X           MenuOldHeight(menu) = MenuHeight(menu);
  1405. X           MenuOldBorderWidth(menu) = MenuBorderWidth(menu);
  1406. X      }
  1407. X      else
  1408. X           SetInputMask(menu, ExposureMask);
  1409. X      
  1410. X      if (MenuSavedPixmap(menu) != (Pixmap) 0) { 
  1411. X           /*    XFillRectangle(dpy,
  1412. X            MenuSavedPixmap(menu),
  1413. X            SaveGC,
  1414. X            0,0,
  1415. X            MenuWidth(menu) + 2*MenuBorderWidth(menu),
  1416. X            MenuHeight(menu) + 2*MenuBorderWidth(menu)); */
  1417. X           SetInputMask(menu, MenuIgnoreMask);
  1418. X           XCopyArea(dpy, 
  1419. X             RootWindow(dpy, scr),
  1420. X             MenuSavedPixmap(menu),
  1421. X             MenuNormalGC(menu),
  1422. X             MenuX(menu), 
  1423. X             MenuY(menu), 
  1424. X             (unsigned int) (MenuWidth(menu) + 2*MenuBorderWidth(menu)), 
  1425. X             (unsigned int) (MenuHeight(menu) + 2*MenuBorderWidth(menu)), 
  1426. X             0, 0);
  1427. X      }
  1428. X      else
  1429. X           SetInputMask(menu, ExposureMask);
  1430. X      
  1431. X     }
  1432. X     
  1433. X     XRaiseWindow(dpy, MenuWindow(menu));
  1434. X     XMapWindow(dpy, MenuWindow(menu));
  1435. X     SetMenuFlag(menu, menuMapped);
  1436. X     Leave(TRUE)
  1437. X}
  1438. X
  1439. Xstatic void Generate_Menu_Entries (menu)
  1440. XMenu *menu;
  1441. X{
  1442. X     MenuItem *item;
  1443. X     
  1444. X     Entry("Generate_Menu_Entries")
  1445. X
  1446. X     for (item = MenuItems(menu); item; (item = ItemNext(item))) {
  1447. X      
  1448. X      if (ItemGenerator(item)) {
  1449. X           char *newText;
  1450. X           
  1451. X           (ItemGenerator(item)) (&newText, &ItemCallback(item));
  1452. X           SetItemText (menu, item, newText);
  1453. X      }
  1454. X      
  1455. X      if (ItemCheckproc(item))
  1456. X           SetItemCheck (menu, item, (ItemCheckproc(item))(menu,item));
  1457. X     }
  1458. X     Leave_void
  1459. X}
  1460. X
  1461. X/*
  1462. X * Draw the entire menu in the blank window.
  1463. X */
  1464. Xvoid Draw_Menu(menu)
  1465. XMenu *menu;
  1466. X{
  1467. X     MenuItem *item;
  1468. X     
  1469. X     Entry("Draw_Menu")
  1470. X
  1471. X     ResetMenuFlag(menu, menuChanged);
  1472. X     /*
  1473. X      * For each item in the list, first draw any check mark and then
  1474. X      * draw the rest of it.
  1475. X      */
  1476. X     for(item = MenuItems(menu) ; item ; item = ItemNext(item)) {
  1477. X      if (TestOptionFlag(menu, savebits))
  1478. X      {
  1479. X           /* go ahead and draw it, don't wait for exposes */
  1480. X           Draw_Item(menu, item);
  1481. X      }
  1482. X     }
  1483. X     Leave_void
  1484. X}
  1485. X
  1486. X/*
  1487. X * Draw the item  at vertical position y.
  1488. X */
  1489. Xvoid Draw_Item(menu, item)
  1490. XMenu *menu;
  1491. XMenuItem *item;
  1492. X{
  1493. X     int y;  /* baseline */
  1494. X     int x = MenuItemPad(menu);
  1495. X     int x1 = 2 * MenuItemPad(menu) + checkMarkWidth;
  1496. X     int pad;
  1497. X     int high;
  1498. X     XGCValues gcValues;
  1499. X     GC theGC;
  1500. X
  1501. X     Entry("Draw_Item")
  1502. X
  1503. X     high = (MenuItemHighlighted(menu) == item);
  1504. X     theGC = high ? MenuInvertGC(menu) : MenuNormalGC(menu);
  1505. X
  1506. X     if (TestItemFlag(item, itemDisabled))
  1507. X     {
  1508. X      gcValues.fill_style = FillOpaqueStippled;
  1509. X      XChangeGC(dpy, theGC, (GCFillStyle), &gcValues);
  1510. X     }
  1511. X     
  1512. X     if (!item->itemBackground) {
  1513. X      XFillRectangle(dpy, ItemWindow(item),
  1514. X             (high) ? MenuNormalGC(menu) : MenuInvertGC(menu),
  1515. X             0, 0, MenuWidth(menu), item->itemHeight);
  1516. X      
  1517. X      /*
  1518. X       * Draw the check mark, possibly dimmed, wherever is necessary.
  1519. X       */
  1520. X     }
  1521. X     if(TestItemFlag(item, itemChecked)){
  1522. X      XCopyArea (dpy, MenuCheckmarkPixmap(menu),
  1523. X             ItemWindow(item),
  1524. X             theGC,
  1525. X             0, 0, checkMarkWidth, checkMarkHeight,
  1526. X             (int) x, (item->itemHeight - checkMarkHeight) / 2);
  1527. X     }
  1528. X     /* Draw submenu indicator arrow */
  1529. X     if(ItemSubmenu(item)) {
  1530. X      XCopyArea (dpy, MenuArrowPixmap(menu),
  1531. X             ItemWindow(item),
  1532. X             theGC,
  1533. X             0, 0,
  1534. X             arrow_width, arrow_height,
  1535. X             (int) (x + MenuItemWidth(menu) -
  1536. X                arrow_width - MenuItemPad(menu)),
  1537. X             (item->itemHeight - arrow_height) / 2 - 1);
  1538. X     }
  1539. X     /*
  1540. X      * Draw the text, centered vertically.
  1541. X      */
  1542. X     if (!item->itemBackground) {
  1543. X      if (!TestItemFlag(item, itemDeaf)) {
  1544. X           pad = (item->itemHeight - 
  1545. X              (MFontInfo->ascent + MFontInfo->descent)) / 2;
  1546. X           y = item->itemHeight - pad - MFontInfo->descent;
  1547. X           
  1548. X           XDrawImageString(dpy, ItemWindow(item),
  1549. X                theGC,
  1550. X                x1, y, ItemText(item), ItemTextLength(item));
  1551. X           if (TestItemFlag(item, itemDisabled))
  1552. X           { 
  1553. X            gcValues.fill_style = FillSolid;
  1554. X            XChangeGC(dpy, theGC,
  1555. X                  (GCFillStyle), &gcValues);
  1556. X           }
  1557. X           
  1558. X      }
  1559. X      else {
  1560. X           pad = (item->itemHeight - (MBoldFontInfo->ascent +
  1561. X                      MBoldFontInfo->descent)) / 2;
  1562. X           y = item->itemHeight - pad - MBoldFontInfo->descent;
  1563. X           XDrawImageString(dpy, ItemWindow(item), menu->boldGC, x1, y,
  1564. X                ItemText(item), ItemTextLength(item));
  1565. X      }
  1566. X     }
  1567. X     Leave_void
  1568. X}
  1569. X
  1570. X
  1571. X/*
  1572. X * UnmapMenu() unmaps a menu, if it is currently mapped.
  1573. X */
  1574. Xstatic void UnmapMenu(menu)
  1575. XMenu *menu;
  1576. X{
  1577. X     Entry("UnmapMenu")
  1578. X
  1579. X     if(!menu || !(TestMenuFlag(menu, menuMapped)))
  1580. X      Leave_void
  1581. X     XUnmapWindow(dpy, MenuWindow(menu));
  1582. X     
  1583. X     if (TestOptionFlag(menu, savebits))
  1584. X     {
  1585. X      if (MenuSavedPixmap(menu))
  1586. X           XCopyArea (dpy,
  1587. X              MenuSavedPixmap(menu),
  1588. X              RootWindow (dpy, scr),
  1589. X              MenuNormalGC(menu),
  1590. X              0, 0, 
  1591. X              MenuWidth(menu) + 2*MenuBorderWidth(menu),
  1592. X              MenuHeight(menu) + 2*MenuBorderWidth(menu),
  1593. X              MenuX(menu), MenuY(menu));
  1594. X      
  1595. X     }
  1596. X     ResetMenuFlag(menu, menuMapped);
  1597. X     Leave_void
  1598. X}
  1599. X
  1600. X
  1601. Xstatic Boolean SetupMenuWindow (menu)
  1602. XMenu *menu;
  1603. X{
  1604. X     int changed = TestMenuFlag(menu, (menuChanged | menuItemChanged));
  1605. X     Entry("SetupMenuWindow")
  1606. X
  1607. X     if (contexts_created == FALSE) {
  1608. X      contexts_created = TRUE;
  1609. X      Menu_context = XUniqueContext(); 
  1610. X      Item_context = XUniqueContext();
  1611. X     }
  1612. X     
  1613. X     /*
  1614. X      * If the entire menu has changed, throw away any saved pixmap and
  1615. X      * then call RecalcMenu().
  1616. X      */
  1617. X     
  1618. X     if(changed & menuChanged) {
  1619. X      if(!Recalc_Menu(menu))
  1620. X           Leave(FALSE)
  1621. X      changed &= ~menuItemChanged;
  1622. X     }
  1623. X     
  1624. X     if(!MenuWindow(menu)) {
  1625. X      static unsigned long valuemask =
  1626. X           CWOverrideRedirect | CWBorderPixel | CWBackPixel;
  1627. X      XSetWindowAttributes attributes;
  1628. X      
  1629. X      attributes.override_redirect = True;
  1630. X      attributes.border_pixel = MBorder;
  1631. X      attributes.background_pixel = MBackground;
  1632. X      if (SaveUnder) {
  1633. X           attributes.save_under = True;
  1634. X           valuemask |= CWSaveUnder;
  1635. X      }
  1636. X
  1637. X      if((MenuWindow(menu) =
  1638. X          XCreateWindow(dpy, 
  1639. X                RootWindow(dpy, scr),
  1640. X                0, 0,
  1641. X                MenuWidth(menu), MenuHeight(menu),
  1642. X                MenuBorderWidth(menu),
  1643. X                DefaultDepth(dpy, scr),
  1644. X                InputOutput, 
  1645. X                DefaultVisual(dpy, scr),
  1646. X                valuemask, &attributes)
  1647. X          ) == (Window)0)
  1648. X           Leave(FALSE)
  1649. X      else if (SetupItems(menu) == FALSE)
  1650. X           Leave(FALSE)
  1651. X
  1652. X      XSaveContext(dpy, MenuWindow(menu), Menu_context, (char *) menu);
  1653. X      XMapSubwindows(dpy, MenuWindow(menu));
  1654. X      
  1655. X      XDefineCursor(dpy, MenuWindow(menu), MenuCursor(menu));
  1656. X     }
  1657. X     else if(changed & menuChanged) {
  1658. X      XResizeWindow(dpy, MenuWindow(menu),
  1659. X            MenuWidth(menu), MenuHeight(menu));
  1660. X      if (SetupItems(menu) == FALSE)
  1661. X           Leave(FALSE)
  1662. X      XMapSubwindows(dpy, MenuWindow(menu));
  1663. X     }
  1664. X     Leave(TRUE)
  1665. X}
  1666. X
  1667. Xstatic Boolean SetupItems(menu)
  1668. XMenu *menu;
  1669. X{
  1670. X     int y;
  1671. X     MenuItem *item;
  1672. X     int changed = TestMenuFlag(menu, (menuChanged | menuItemChanged));
  1673. X
  1674. X     Entry("SetupItems")
  1675. X     
  1676. X     for (item = MenuItems(menu), y = 0; item;
  1677. X      y += item->itemHeight, item = ItemNext(item)) {
  1678. X      if (!ItemWindow(item)) {
  1679. X           static unsigned long valuemask =
  1680. X            (CWOverrideRedirect | CWBorderPixel | CWBackPixel);
  1681. X           XSetWindowAttributes attributes;
  1682. X
  1683. X           attributes.override_redirect = True;
  1684. X           attributes.border_pixel = MBorder;
  1685. X           attributes.background_pixel = MBackground;
  1686. X
  1687. X           if((ItemWindow(item) =
  1688. X           XCreateWindow(dpy, 
  1689. X                 MenuWindow(menu),
  1690. X                 0, y, 
  1691. X                 MenuItemWidth(menu), 
  1692. X                 item->itemHeight - (2 * MItemBorder), 
  1693. X                 MItemBorder,
  1694. X                 DefaultDepth(dpy, scr),
  1695. X                 InputOutput, 
  1696. X                 DefaultVisual(dpy, scr),
  1697. X                 valuemask, &attributes)
  1698. X           ) == (Window) 0)
  1699. X            Leave(FALSE)
  1700. X           if (item->itemBackground) {
  1701. X            XSetWindowBackgroundPixmap(dpy, ItemWindow(item),
  1702. X                           item->itemBackground);
  1703. X            XFreePixmap(dpy, item->itemBackground);
  1704. X           }
  1705. X           ItemMenu(item) = menu;
  1706. X           XSaveContext(dpy, ItemWindow(item), Item_context,
  1707. X                (char *) item);
  1708. X           XDefineCursor(dpy, ItemWindow(item),
  1709. X                 MenuCursor(menu));
  1710. X      }
  1711. X      
  1712. X      else if (changed & menuChanged) {
  1713. X           XResizeWindow(dpy, ItemWindow(item),
  1714. X                 MenuItemWidth(menu), 
  1715. X                 item->itemHeight - (2 * MItemBorder));
  1716. X           XMoveWindow(dpy, ItemWindow(item), 0, y);
  1717. X      }
  1718. X     }
  1719. X     Leave(TRUE)
  1720. X}
  1721. X
  1722. Xstatic void SetInputMask(menu, mask)
  1723. XMenu *menu;
  1724. Xunsigned int mask;
  1725. X{
  1726. X     MenuItem *item;
  1727. X     Entry("SetInputMask")
  1728. X
  1729. X     XSelectInput(dpy, MenuWindow(menu),
  1730. X          (mask | MenuEventMask));
  1731. X     for(item = MenuItems(menu) ; item ; item = ItemNext(item))
  1732. X     {
  1733. X      if (TestItemFlag(item, itemDisabled) || TestItemFlag(item, itemDeaf))
  1734. X           XSelectInput(dpy, ItemWindow(item),
  1735. X                (mask | MenuIgnoreMask));
  1736. X      else if (ItemIsLeaf(item))
  1737. X           XSelectInput(dpy, ItemWindow(item),
  1738. X                (mask | NormalItemEventMask));
  1739. X      else
  1740. X           XSelectInput(dpy, ItemWindow(item),
  1741. X                (mask | SubmenuItemEventMask));
  1742. X     }
  1743. X     Leave_void
  1744. X}
  1745. X
  1746. XMenuItem *MenuItemByData(menu, data)
  1747. XMenu* menu;
  1748. Xpointer data;
  1749. X{
  1750. X     MenuItem *item;
  1751. X     
  1752. X     Entry("MenuItemByData")
  1753. X
  1754. X     for (item = MenuItems(menu);
  1755. X      !ItemIsNull(item) && (ItemData(item) != data);
  1756. X      item = ItemNext(item));
  1757. X     
  1758. X     Leave(item)
  1759. X}   
  1760. X
  1761. XMenuItem *MenuItemByName (menu, name)
  1762. XMenu *menu;
  1763. Xchar *name;
  1764. X{
  1765. X     MenuItem *item;
  1766. X
  1767. X     Entry("MenuItemByName")
  1768. X
  1769. X     for (item = MenuItems(menu); item; item = ItemNext(item))
  1770. X      if (strcmp (name, ItemText(item)) == 0)
  1771. X           Leave(item)
  1772. X     Leave(NULLITEM)
  1773. X}
  1774. X
  1775. XMenuItem *MenuGetItem(menu, window) 
  1776. XMenu *menu;
  1777. XWindow window;
  1778. X{    
  1779. X     MenuItem *foo = 0;
  1780. X     Window tmpwindow = window;
  1781. X
  1782. X     Entry("MenuGetItem")
  1783. X
  1784. X     if (!menu || !window)
  1785. X      Leave(NULLITEM)
  1786. X     if (window == menu->menuWindow)
  1787. X      if (menu->highlightedItem)
  1788. X           tmpwindow = menu->highlightedItem->itemWindow;
  1789. X     XFindContext(dpy, tmpwindow, Item_context, &foo);
  1790. X     Leave(foo)
  1791. X}
  1792. X
  1793. XMenu *MenuGetMenu(menu, window)
  1794. XMenu *menu;
  1795. XWindow window;
  1796. X{
  1797. X     Menu *bar = 0;
  1798. X     Entry("MenuGetMenu")
  1799. X
  1800. X     XFindContext(dpy, window, Menu_context, &bar);
  1801. X     Leave(bar)
  1802. X}
  1803. X
  1804. Xint ItemGetMiddleY(item)
  1805. XMenuItem *item;
  1806. X{
  1807. X     Window child;
  1808. X     XWindowAttributes attributes;
  1809. X     int x, y;
  1810. X     Entry("ItemGetMiddleY")
  1811. X
  1812. X     XGetWindowAttributes(dpy, ItemWindow(item), &attributes);
  1813. X     XTranslateCoordinates(dpy,
  1814. X               MenuWindow(ItemMenu(item)), 
  1815. X               RootWindow(dpy, scr),
  1816. X               attributes.x, attributes.y, 
  1817. X               &x, &y, &child);
  1818. X     Leave((item->itemHeight / 2) + y)
  1819. X}
  1820. X
  1821. Xvoid SetInitialItem(menu, item)
  1822. XMenu *menu;
  1823. XMenuItem *item;
  1824. X{
  1825. X     extern char *realloc();
  1826. X     
  1827. X     Entry("SetInitialItem")
  1828. X
  1829. X     if (MenuHasInitialItem(menu)) {
  1830. X      if (strlen(MenuInitialItemText(menu)) < strlen(ItemText(item)))
  1831. X           MenuInitialItemText(menu) =
  1832. X            realloc(MenuInitialItemText(menu), 
  1833. X                strlen(ItemText(item)) + 1);
  1834. X     }
  1835. X     else
  1836. X      MenuInitialItemText(menu) =
  1837. X           allocate(char,(strlen(ItemText(item)) + 1));
  1838. X     strcpy(MenuInitialItemText(menu), ItemText(item));
  1839. X     Leave_void
  1840. X}
  1841. X
  1842. Xvoid ClearInitialItem(menu)
  1843. XMenu *menu;
  1844. X{
  1845. X     Entry("ClearInitialItem")
  1846. X
  1847. X     if (MenuHasInitialItem(menu)) {
  1848. X      free(MenuInitialItemText(menu));
  1849. X      MenuInitialItemText(menu) = (char *) NULL;
  1850. X     }
  1851. X     Leave_void
  1852. X}
  1853. X
  1854. XMenuItem *GetInitialItem(menu)
  1855. XMenu *menu;
  1856. X{
  1857. X     MenuItem *item;
  1858. X     
  1859. X     Entry("GetInitialItem")
  1860. X
  1861. X     if (MenuHasInitialItem(menu)) {
  1862. X      for(item = MenuItems(menu) ; item ; item = ItemNext(item)) {
  1863. X           if (ItemIsInitialItem(menu, item))
  1864. X            Leave(item)
  1865. X      }
  1866. X     }
  1867. X     Leave((MenuItem *) NULL)
  1868. X}
  1869. X
  1870. X
  1871. X/* Some utility functions */
  1872. X
  1873. Xvoid Retch(s, p1, p2, p3, p4)
  1874. Xchar *s;
  1875. Xlong p1, p2, p3, p4;
  1876. X{
  1877. X     char buffer[1024];
  1878. X     
  1879. X     sprintf(buffer, s, p1, p2, p3, p4);
  1880. X     fprintf(stderr, "Error in %s %s\n", curr_rtn(), buffer);
  1881. X     return;
  1882. X}
  1883. END_OF_FILE
  1884. if test 33843 -ne `wc -c <'menus/menu.c'`; then
  1885.     echo shar: \"'menus/menu.c'\" unpacked with wrong size!
  1886. fi
  1887. # end of 'menus/menu.c'
  1888. fi
  1889. if test -f 'menus/menu.ext.h' -a "${1}" != "-c" ; then 
  1890.   echo shar: Will not clobber existing file \"'menus/menu.ext.h'\"
  1891. else
  1892. echo shar: Extracting \"'menus/menu.ext.h'\" \(1789 characters\)
  1893. sed "s/^X//" >'menus/menu.ext.h' <<'END_OF_FILE'
  1894. X
  1895. X/*
  1896. X#ifndef lint
  1897. Xstatic char sccs_id[] = "@(#)menu.extern.h    2.1 12/16/87  Siemens Corporate Research and Support, Inc.";
  1898. X#endif
  1899. X*/
  1900. X
  1901. X
  1902. X/* 
  1903. X  RTL Menu Package Version 1.0
  1904. X  by Joe Camaratta and Mike Berman, Siemens RTL, Princeton NJ, 1987
  1905. X
  1906. X  menu.extern.h: external function declarations for menu package
  1907. X*/
  1908. X
  1909. X#include "X11/copyright.h"
  1910. X/*
  1911. X *
  1912. X * Copyright 1987, 1988 by Ardent Computer Corporation, Sunnyvale, Ca.
  1913. X *
  1914. X * Copyright 1987 by Jordan Hubbard.
  1915. X *
  1916. X *
  1917. X *                         All Rights Reserved
  1918. X *
  1919. X * Permission to use, copy, modify, and distribute this software and its
  1920. X * documentation for any purpose and without fee is hereby granted,
  1921. X * provided that the above copyright notice appear in all copies and that
  1922. X * both that copyright notice and this permission notice appear in
  1923. X * supporting documentation, and that the name of Ardent Computer
  1924. X * Corporation or Jordan Hubbard not be used in advertising or publicity
  1925. X * pertaining to distribution of the software without specific, written
  1926. X * prior permission.
  1927. X *
  1928. X */
  1929. X
  1930. Xextern MenuItem *AddMenuItem();
  1931. Xextern Boolean     DisposeItem();
  1932. Xextern void     DisposeMenu();
  1933. Xextern void     InitMenu();
  1934. Xextern Boolean     SetItemText();
  1935. Xextern Menu     *NewMenu();
  1936. Xextern Boolean     SetItemCheck();
  1937. Xextern Boolean     SetItemDisable();
  1938. Xextern MenuItem *Display_Menu();
  1939. Xextern void     Undisplay_Menu();
  1940. Xextern void     MenuInvert();
  1941. Xextern void     PlacePointer();
  1942. Xextern void     Draw_Menu();
  1943. Xextern void     Draw_Item();
  1944. X
  1945. Xextern MenuItem *MenuGetItem();
  1946. Xextern MenuItem *MenuItemByName();
  1947. Xextern MenuItem *MenuItemByData();
  1948. Xextern Menu     *MenuGetMenu();
  1949. Xextern int      ItemGetMiddleY();
  1950. Xextern void     SetInitialItem();
  1951. Xextern void     ClearInitialItem();
  1952. Xextern MenuItem *GetInitialItem();
  1953. X
  1954. Xextern MenuItem *TrackMenu();
  1955. X
  1956. X
  1957. X
  1958. X
  1959. X
  1960. X
  1961. X
  1962. X
  1963. X
  1964. X
  1965. END_OF_FILE
  1966. if test 1789 -ne `wc -c <'menus/menu.ext.h'`; then
  1967.     echo shar: \"'menus/menu.ext.h'\" unpacked with wrong size!
  1968. fi
  1969. # end of 'menus/menu.ext.h'
  1970. fi
  1971. echo shar: End of archive 3 \(of 12\).
  1972. cp /dev/null ark3isdone
  1973. MISSING=""
  1974. for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
  1975.     if test ! -f ark${I}isdone ; then
  1976.     MISSING="${MISSING} ${I}"
  1977.     fi
  1978. done
  1979. if test "${MISSING}" = "" ; then
  1980.     echo You have unpacked all 12 archives.
  1981.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1982. else
  1983.     echo You still need to unpack the following archives:
  1984.     echo "        " ${MISSING}
  1985. fi
  1986. ##  End of shell archive.
  1987. exit 0
  1988. -- 
  1989. Mike Wexler(wyse!mikew)    Phone: (408)433-1000 x1330
  1990. Moderator of comp.sources.x
  1991.